package com.itheima.stock.service.impl;

import com.google.common.collect.Lists;
import com.itheima.stock.common.StockInfoConfig;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBlockRtInfo;
import com.itheima.stock.pojo.StockMarketIndexInfo;
import com.itheima.stock.pojo.StockRtInfo;
import com.itheima.stock.service.StockTimerTaskService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.utils.ParserStockInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StockTimerTaskServiceImpl implements StockTimerTaskService {

    //数据配置
    @Autowired
    private StockInfoConfig stockInfoConfig;

    //加载唯一id生成
    @Autowired
    private IdWorker idWorker;

    //注入模板对象
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Autowired
    StockBusinessMapper stockBusinessMapper;

    @Autowired
    ParserStockInfoUtil parserStockInfoUtil;

    @Autowired
    StockRtInfoMapper stockRtInfoMapper;

    @Autowired
    StockBlockRtInfoMapper stockBlockRtInfoMapper;

    //注入线程池对象
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 获取国内大盘的实时数据信息
     * var hq_str_s_sh000001="上证指数,3534.1672,-21.0913,-0.59,2245894,26963537";
     */
    @Override
    public void getInnerMarketInfo() {
        //组装动态url
        //http://hq.sinajs.cn/list=s_sh000001,s_sz399001
        String marketUrl = stockInfoConfig.getMarketUrl() + String.join(",",stockInfoConfig.getInner());
        //发起请求(get)
        String result = restTemplate.getForObject(marketUrl, String.class);
        //正则解析
        String pattern = "var hq_str_(.+)=\"(.+)\";";
        Pattern compile = Pattern.compile(pattern);
        Matcher matcher = compile.matcher(result);
        //收集大盘封装后后的对象
        ArrayList<StockMarketIndexInfo> infos = new ArrayList<>();
        while (matcher.find()) {
            //获取大盘的id
            String id = matcher.group(1);
            System.out.println("group = " + id);
            //其他信息，需要进行切割
            //"上证指数,3534.1672,-21.0913,-0.59,2245894,26963537"
            String msg = matcher.group(2);
            String[] split = msg.split(",");
            //大盘名称
            String marketName = split[0];
            //当前点
            BigDecimal curPoint=new BigDecimal(split[1]);
            //当前价格
            BigDecimal curPrice=new BigDecimal(split[2]);
            //涨跌率
            BigDecimal upDownRate=new BigDecimal(split[3]);
            //成交量
            Long tradeAmount=Long.valueOf(split[4]);
            //成交金额
            Long tradeVol=Long.valueOf(split[5]);
            //封装成对象，用建造者模式,注意id使用雪花算法生成
            StockMarketIndexInfo stockMarketIndexInfo = StockMarketIndexInfo.builder().id(idWorker.nextId())
                    .markName(marketName)
                    .curPoint(curPoint)
                    .currentPrice(curPrice)
                    .updownRate(upDownRate)
                    .tradeAccount(tradeAmount)
                    .tradeVolume(tradeVol)
                    .curTime(new Date())
                    .markId(id).build();
            infos.add(stockMarketIndexInfo);
        }

        //批量插入数据库，数据少就不用分批
        //stockMarketIndexInfoMapper.insertBatch(infos);

        //测试
        String curTime = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss"));
        log.info("采集的大盘数据：{},当前时间：{}",infos,curTime);
    }

    /**
     * 定义获取分钟级A股股票数据
     */
    @Override
    public void getStockRtIndex() {
        //从表中获取股票id合集
        List<String> allStockId = stockBusinessMapper.findAllStockId();
        //深证：A：以0开头 上证：6开头
        List<String> collect = allStockId.stream().map(id -> {
            return id.startsWith("6") ? "sh" + id : "sz" + id;
        }).collect(Collectors.toList());

        //数据太多一次性插入效率低,分组插入,将集合分组，每组的集合长度为20
        //google.common工具类可快速将集合分组
        Lists.partition(collect,20).forEach(ids->{
            //多线程执行，也可以使用匿名内部类
            threadPoolTaskExecutor.execute(()->{
                //遍历拼接url
                String url = stockInfoConfig.getMarketUrl() + String.join(",",ids);
                //发送请求数据
                String result = restTemplate.getForObject(url, String.class);
                //解析股票类，使用提取编写的工具类
                List<StockRtInfo> list = parserStockInfoUtil.parser4StockOrMarketInfo(result, 3);
                //分批插入,注意插入的是个股涨幅信息表
                //stockRtInfoMapper.insertBatch(list);

                //测试
                String curTime = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss"));
                log.info("采集的A股数据：{},当前时间：{}",list,curTime);
            });

        });

    }

    /**
     * 获取板块数据
     */
    @Override
    public void getStockSectorRtIndex() {
        //拼接url
        String url = stockInfoConfig.getBlockUrl();
        //发送请求
        String result = restTemplate.getForObject(url, String.class);
        //使用工具类解析结果
        List<StockBlockRtInfo> stockBlockRtInfos = parserStockInfoUtil.parse4StockBlock(result);
        //批量插入，先分组
        Lists.partition(stockBlockRtInfos,20).forEach(items->{
            threadPoolTaskExecutor.execute(()->{
                //stockBlockRtInfoMapper.insertBatch(items);
                //测试
                String curTime = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss"));
                log.info("采集的版块数据：{},当前时间：{}",stockBlockRtInfos,curTime);
            });
        });
    }
}
